/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.seclust;

import Annas.Graph.Arc;
import Annas.Graph.Graph;
import Annas.Graph.Node;
import java.util.ArrayList;
import java.util.Arrays;
import Annas.Graph.Drawing.DrawableGraph;
import Annas.Graph.Drawing.ImagePanel;
import javax.swing.JFrame;

/**
 *
 * @author baga
 */
public class ClusteringQuality {

    private Graph resGraph;
    private Graph newGraph;
    private Graph initGraph;
    private String query;
    private WeightTF wt;
    private ArrayList resAL;
    private ArrayList stopWords;
    private boolean isPrep;
    private String tableUse;

    public ClusteringQuality(String query, String table, boolean isPrep) {
        this.query = query;
        this.isPrep = isPrep;
        if(isPrep) {
            tableUse = table + "_" + "prep";
        } else {
            tableUse = table;
        }
        wt = new WeightTF(query, table, isPrep);
    }

    public ArrayList getCorrectList(ArrayList theList) {
        ArrayList abc = theList;
        boolean find = false;
        for (int i = 0; i < abc.size(); i++) {
            ArrayList al = (ArrayList) abc.get(i);
            for (int j = 0; j < al.size(); j++) {
                Integer val = (Integer) al.get(j);
                for (int x = i + 1; x < abc.size(); x++) {
                    ArrayList alx = (ArrayList) abc.get(x);
                    if (alx.contains(val)) {
                        ArrayList xArr = (ArrayList) abc.get(x);
                        for (int z = 0; z < xArr.size(); z++) {
                            Integer valXarr = (Integer) xArr.get(z);
                            if (!al.contains(valXarr)) {
                                al.add(valXarr);
                            }
                        }
                        abc.remove(x);
                    }
                }
            }
        }
        return abc;
    }

    public ArrayList getStopWords() {
        return wt.getStopWords();
    }

    public double qualityK(int k) {
        double[] matDistance = null;
        Double[][] origMatrix = null;
        double summLe = 0.0;
        wt.runMatlan(k);
        stopWords = wt.getStopWords();  // i dont know what this for
        // penghitungan cosinus similarity
        CosSim cs = new CosSim(k, query, tableUse);
        origMatrix = cs.getMatrixResult();

        matDistance = cs.allDistance();
        // penghitungan prims
        Prims pr = new Prims(origMatrix.length, matDistance);
        initGraph = pr.initGraph();   // graph awal
        resGraph = pr.resPrimGraph();   // graph hasil MST
        Double[] edgeValOrig = pr.getEdgesOrig();   // edge2 asli

        Double[] edgeVal = pr.getEdges();   // edge2 hasil MST
        // penghitungan C(e)
        StatFunc sf = new StatFunc(edgeValOrig, edgeVal);
        summLe = sf.getQuality(k - 1);
//        if(summLe < 0) {
//            summLe *= -1;
//        }
        return (k * summLe);
    }

    public LabelClass[] getQuality() {
        // ini harus looping berdasarkan edge hasil MSt
        int k = 2;
        int count = 0;
        ArrayList al = new ArrayList();
        while (true) {
            int prevK = k - 1;
            int curK = k;
            int nextK = k + 1;
            double prevVal, currVal, nextVal;
            prevVal = currVal = nextVal = 0.0;
            currVal = qualityK(curK);
            prevVal = qualityK(prevK);
            nextVal = qualityK(nextK);
            if (currVal < 0) {
                currVal *= -1;
            }

            if (prevVal < 0) {
                prevVal *= -1;
            }

            if (nextVal < 0) {
                nextVal *= -1;
            }
            System.out.println("nilai k " + k + "prev " + prevVal + " curr " + currVal + " next " + nextVal);
            if (prevVal <= currVal && currVal > nextVal) {
                break;
            }

//            System.out.println("nilai k "+ k +"prev " + prevVal + " curr " +currVal + " next " + nextVal );
            k++;
            count++;
        }

        newGraph = resGraph;

        System.out.println("nilai k " + k);
        System.out.println();

        ArrayList<Node> nodeMap = resGraph.getNodeMap();
        ArrayList<Arc> allArcs = new ArrayList();
        for (int i = 0; i < nodeMap.size(); i++) {
            ArrayList<Arc> arcs = nodeMap.get(i).getAdjacent();
            for (int j = 0; j < arcs.size(); j++) {
                allArcs.add(arcs.get(j));
            }
        }

        Arc max = null;
        count = 0;
        for (int i = 0; i < allArcs.size(); i++) {
            max = allArcs.get(i);
            count = i;
            for (int j = i + 1; j < allArcs.size(); j++) {
                if (allArcs.get(j).getWeight() < max.getWeight()) {
                    count = j;
                    max = allArcs.get(j);
                }
            }

            if (count != i) {
                allArcs.set(count, allArcs.get(i));
                allArcs.set(i, max);
            }
        }

        System.out.println("sebelum di potong");
        showGraph(resGraph);
        for (int i = 0; i < k - 1; i++) {
            for (int j = 0; j < nodeMap.size(); j++) {
                ArrayList<Arc> arcs = nodeMap.get(j).getAdjacent();
                for (int z = 0; z < arcs.size(); z++) {
                    if (allArcs.get(i).equals(arcs.get(z))) {
                        System.out.println("yang dipotong " + allArcs.get(i).toString());
                        nodeMap.get(j).removeArc(allArcs.get(i));
                    }
                }
            }
        }
        System.out.println("Setelah di potong");
        showGraph(resGraph);
        ArrayList<ArrayList> corectList = getCorrectList(mergeGraph(resGraph));
        int size;
        String[] contents = wt.getContents();
        System.out.println("Contents size : " + contents.length);
        LabelClass[] labelClass = new LabelClass[corectList.size()];
        for(int i=0; i<corectList.size(); i++) {
            size = corectList.get(i).size();
            String[] arrString = new String[size];
            for(int j=0; j<size; j++) {
                Integer iList = (Integer) corectList.get(i).get(j);
                arrString[j] = contents[iList - 1];
            }
            labelClass[i] = new LabelClass(getLabel(arrString), i);
        }
        resAL = corectList;

        return labelClass;
    }

    public ArrayList getResultAl() {
        return resAL;
    }

    public ImagePanel getPanel() {
        DrawableGraph dg = new DrawableGraph(resGraph);
        dg.doDraw();
        return dg.getImgPanel();
    }

    public ImagePanel getOrigPanel() {
        DrawableGraph dg = new DrawableGraph(newGraph);
        dg.doDraw();

        return dg.getImgPanel();
    }

    public String[] getUrls() {
        return wt.getUrls();
    }

    public String[] getContents() {
        return wt.getContents();
    }

    private void showGraph(Graph theGraph) {
        ArrayList<Node> alNodeMap = theGraph.getNodeMap();
        ArrayList<Arc> arcs = new ArrayList();

        for (int i = 0; i < alNodeMap.size(); i++) {
            System.out.println(alNodeMap.get(i).toString());
            arcs = alNodeMap.get(i).getAdjacent();
            for (int j = 0; j < arcs.size(); j++) {
                System.out.println("\t\t" + arcs.get(j).toString());
            }
        }
    }

    private String getLabel(String[] contents) {
        ArrayList<String> alContent = new ArrayList<String>();
        ArrayList<Double> alDouble = new ArrayList<Double>();
        int idx = 0;
        Double val, max;

        for (String tempString : contents) {
            String[] arrContent = SplitNormalizeToken.getNormalTokensStemmer(tempString);
            for (int i = 0; i < arrContent.length; i++) {
                if ((!arrContent[i].isEmpty() && !arrContent[i].equals("\n")) && !arrContent[i].equals(query)) {
                    if (isPrep) {
                        if (!stopWords.contains(arrContent[i]) && !arrContent[i].equals(query)) {
                            if (alContent.isEmpty() || !alContent.contains(arrContent[i])) {
                                alContent.add(arrContent[i]);
                                alDouble.add(1.0);
                            } else {
                                idx = alContent.indexOf(arrContent[i]);
                                val = (Double) alDouble.get(idx);
                                alDouble.set(idx, ++val);
                            }
                        }
                    } else {
                        if (alContent.isEmpty() || !alContent.contains(arrContent[i])) {
                            alContent.add(arrContent[i]);
                            alDouble.add(1.0);
                        } else {
                            idx = alContent.indexOf(arrContent[i]);
                            val = (Double) alDouble.get(idx);
                            alDouble.set(idx, ++val);
                        }
                    }
                }
            }
        }
        max = -1.0;
        for (int i = 0; i < alDouble.size(); i++) {
            if (alDouble.get(i) > max) {
                max = alDouble.get(i);
                idx = i;
            }
        }
        return alContent.get(idx);
    }

    // fungsi ini digunakan untuk menggabungkan graph yang sebelumnya sudah
    // dihapus sebagian arcnya
    private ArrayList mergeGraph(Graph res) {
        ArrayList<ArrayList> fullArray = new ArrayList();
        ArrayList<Node> allNode = res.getNodeMap();
        ArrayList<Arc> alArcs = null;

        Node aNode = null;
        for (int i = 0; i < allNode.size(); i++) {
            ArrayList<Integer> alArcs2 = new ArrayList();
            alArcs2.add(Integer.parseInt(allNode.get(i).getName()));
//            System.out.print(Integer.parseInt(allNode.get(i).getName()) + " ");
//            if (allNode.get(i).NumArcs() > 0) {
            alArcs = allNode.get(i).getAdjacent();
            for (int j = 0; j < alArcs.size(); j++) {
                alArcs2.add(Integer.parseInt(alArcs.get(j).getHead()));
//                System.out.print(alArcs.get(j).getHead() + " ");
            }
//            System.out.println();
            fullArray.add(alArcs2);
//            }
        }
        return fullArray;
    }

//    private void printArc(Node aNode) {
//        if(aNode.NumArcs() > 0) {
//            ArrayList<Arc> allArc = aNode.getAdjacent();
//            for(int i=0; i<allArc.size(); i++) {
//                Node nodeHead = allArc.get(i).getHead();
//            }
//        }
//    }
    public static void main(String[] args) {

        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                ClusteringQuality cq = new ClusteringQuality("DMOZsamples3", "t_clust", true);
                LabelClass[] lb = cq.getQuality();
                JFrame.setDefaultLookAndFeelDecorated(true);

                //Create and set up the window.
                JFrame frame = new JFrame("HelloWorldSwing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                //Add the ubiquitous "Hello World" label.
//                JLabel label = new JLabel("Hello World");
                frame.getContentPane().add(cq.getPanel());

                //Display the window.
                frame.pack();
                frame.setVisible(true);
                for(int i=0; i<lb.length; i++) {
                    System.out.println(lb[i].getLabel());
                }

            }
        });

    }
}
